In this assignment we implemented Dataset and Dataloades classes on students faces data that we uploaded to the drive.
We chose augmentations that we think will be good for use in face recognition and we applied them on our dataset.
Moreover, we implemented OpenCV face detection algorithm and swapped between 2 faces in different images (there are examples in the code).
import torch
import numpy as np
import random
import matplotlib.pyplot as plt
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
import torchvision
from torch.utils.data import Dataset , DataLoader
from sklearn.model_selection import train_test_split
import albumentations as A
import cv2
import os
from google.colab import drive
drive.mount("/content/drive", force_remount=True)
GOOGLE_DRIVE_PATH_AFTER_MY_DRIVE = 'Computer Vision/Afeka_CV_2021/'
GOOGLE_DRIVE_PATH = os.path.join('drive', 'My Drive', GOOGLE_DRIVE_PATH_AFTER_MY_DRIVE)
SEED = 0
class FacesData:
def __init__(self, path):
self.images = []
self.labels = []
for folder in os.listdir(path):
folder_path = os.path.join(path, folder)
for file in os.listdir(folder_path):
self.labels.append(folder)
img_path = os.path.join(folder_path, file)
img = cv2.imread(img_path)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
self.images.append(img)
self.images = np.array(self.images)
self.labels = np.array(self.labels)
def load_data(self, train_size=.8):
if train_size > 1 or train_size < 0:
raise ValueError("Split sizes can not be greater than 1 or less than 0")
test_size = 1 - train_size
x_train, x_test, y_train, y_test = train_test_split(self.images, self.labels, test_size=test_size, random_state=SEED)
return (x_train, y_train), (x_test, y_test)
students_number = len(os.listdir(GOOGLE_DRIVE_PATH))
plt.figure(figsize=(25, 10))
for index, folder in zip(range(students_number), os.listdir(GOOGLE_DRIVE_PATH)):
plt.subplot(4, 10, index + 1)
folder_path = os.path.join(GOOGLE_DRIVE_PATH, folder)
img_path = os.path.join(folder_path, os.listdir(folder_path)[0])
img = cv2.imread(img_path)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.title(folder)
plt.axis("off")
plt.imshow(img)
plt.show()
class FacesDataSet(Dataset):
def __init__(self, data, labels, transforms=None):
self.x = data
self.y = labels
self.transforms = transforms
def __getitem__(self, idx):
x = self.x[idx]
y = self.y[idx]
x = cv2.resize(x, (224, 224), cv2.INTER_AREA)
if self.transforms:
x = self.transforms(image = x)
x = x['image']
x = torch.from_numpy(x)
return x, y
def __len__(self):
return len(self.x)
Randomly rearrange channels of the input RGB image.

Docstring for MotionBlur Apply motion blur to the input image using a random-sized kernel.

If the blur_limit get high values, it may affect on the image recognition.
for example:

Randomly change the brightness of the input image.

If the limit get too high or too low values we will see too bright/dark image.
for example:

Rotate the input by an angle selected randomly from the uniform distribution.

Decreases image quality by downscaling and upscaling back.

The Blur limit should get low values in order not to ruin the image.
for example:

transformations = A.Compose([
A.ChannelShuffle(p=0.3),
A.MotionBlur(blur_limit=10, p=0.3),
A.RandomBrightness(limit=(-0.2, 0.2), p=0.3),
A.Rotate(limit=(0,360), p=0.3),
A.Blur(blur_limit=10, p=0.3),
A.GaussNoise(var_limit=(0, 500), p=0.3),
])
faces = FacesData(GOOGLE_DRIVE_PATH)
(x_train, y_train), (x_test, y_test)= faces.load_data()
trainset = FacesDataSet(x_train, y_train, transformations)
testset = FacesDataSet(x_test, y_test, transformations)
BS=32
faces_loader_train = DataLoader(dataset=trainset, batch_size= BS, shuffle=True)
faces_loader_test = DataLoader(dataset=testset, batch_size= BS, shuffle=False)
imgs, lbls = next(iter(faces_loader_train))
plt.figure(figsize=(20, 10))
for index, img, lbl in zip(range(BS), imgs, lbls):
plt.subplot(4, 8, index + 1)
plt.title(lbl)
plt.axis("off")
plt.imshow(img)
plt.show()
def detect_face(img):
# img = np.array(img)
cascade = cv2.CascadeClassifier('haarcascade_frontalface_alt2.xml')
gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
detected = cascade.detectMultiScale(gray_img, 1.3, 5)
return detected[0]
ids = [6, 7, 8, 12, 14]
plt.figure(figsize=(20, 10))
for index, id in zip(range(len(ids)), ids):
plt.subplot(1, 5, index + 1)
det = detect_face(x_train[id])
image = x_train[id].copy()
detected = cv2.rectangle(image, (det[0], det[1]), (det[0]+det[2], det[1]+det[3]), (0, 255, 0), 7)
plt.title(y_train[id])
plt.axis("off")
plt.imshow(detected)
plt.show()
#Change the face of the first image to the face in the second image
def plant_face(img1, img2):
det1 = detect_face(img1)
det2 = detect_face(img2)
img1_cpy = img1.copy()
face2 = img2[det2[1]:det2[1]+det2[3],det2[0]:det2[0]+det2[2]]
face2 = cv2.resize(face2,(det1[3],det1[2]),cv2.INTER_LINEAR)
img1_cpy[det1[1]:det1[1]+det1[3],det1[0]:det1[0]+det1[2]] = face2 #swap the faces
return img1_cpy
tuple_indexes = [(6, 7), (7, 8), (8, 12), (12, 14), (14, 6)]
for index, (id1, id2) in zip(range(len(tuple_indexes)), tuple_indexes):
swapped = plant_face(x_train[id1],x_train[id2])
plt.figure(figsize=(20, 10))
plt.subplot(1, 3, 1)
plt.title(y_train[id1])
plt.axis("off")
plt.imshow(x_train[id1])
plt.subplot(1, 3, 2)
plt.title(y_train[id2])
plt.axis("off")
plt.imshow(x_train[id2])
plt.subplot(1, 3, 3)
plt.title("Face Swapped Image")
plt.axis("off")
plt.imshow(swapped)
plt.show()